package com.atjava.nebula.web.json;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.BeanPropertyDefinition;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.SerializerProvider;
import org.codehaus.jackson.map.ser.CustomSerializerFactory;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;

import com.atjava.nebula.core.constant.Constant;
import com.atjava.nebula.core.tablexml.view.Column;
import com.atjava.nebula.core.tablexml.view.Grid;
import com.atjava.nebula.eims.comdoc.model.MoDocDef;
import com.atjava.nebula.eims.comdoc.model.MoDocList;
import com.atjava.nebula.eims.comdoc.model.MoDocValue;
import com.atjava.nebula.web.collections.GridDataList;
import com.atjava.nebula.web.constant.ProjectConst;
import com.atjava.nebula.web.view.XmlViewManager;

/**
 * 
 * @author jin-dong
 *
 */
public class JsonObjectMapper extends ObjectMapper {

	@SuppressWarnings("rawtypes")
	public JsonObjectMapper() {
		CustomSerializerFactory factory = new CustomSerializerFactory();
		factory.addGenericMapping(Date.class, new JsonSerializer<Date>() {
			@Override
			public void serialize(Date value, JsonGenerator jsonGenerator,
					SerializerProvider provider) throws IOException,
					JsonProcessingException {
				SimpleDateFormat sdf = new SimpleDateFormat(
						Constant.DEFAULT_TIME_FORMAT);
				jsonGenerator.writeString(sdf.format(value));
			}
		});
		
		factory.addSpecificMapping(MoDocList.class,new JsonSerializer<MoDocList>() {

			public void serialize(MoDocList list,
					JsonGenerator jsonGenerator,
					SerializerProvider provider) throws IOException{
				
				jsonGenerator.writeStartArray();
				
				//document data
				List<MoDocValue> data = list.getDocData();
				//document define
				MoDocDef def = list.getDocDef();
				
				Md5PasswordEncoder md5Encoder = new Md5PasswordEncoder();
				String [] docHeader = def.getHeader().split(ProjectConst.SPLIT_KEY_DOC_COLUMN);
				String [] queryIndexes = def.getQueryIndex().split(ProjectConst.SPLIT_KEY_DOC_QUERY_INDEX);
				Set<Short> queryIndexSet = new HashSet<Short>();
				for (int i = 0; i < queryIndexes.length; i++) {
					queryIndexSet.add(Short.parseShort(queryIndexes[i]));
				}
				
				for (int i = 0; i < data.size(); i++) {
					
					
					MoDocValue docRowData = data.get(i);
					String [] otherColumnData = docRowData.getText().split(ProjectConst.SPLIT_KEY_DOC_COLUMN);
					
					jsonGenerator.writeStartObject();
					
					int queryColCounter = 0;
					int userColCounter = 0;
					for (short j = 0; j < docHeader.length; j++) {
						
						String columnHeader = md5Encoder.encodePassword(docHeader[j], null);
						columnHeader = columnHeader.substring(0, 8);
						
						//is query column
						if(queryIndexSet.contains(j)){
							if(queryColCounter == 0){
								jsonGenerator.writeObjectField(columnHeader, docRowData.getQueryCol1());
							}else if(queryColCounter == 1){
								jsonGenerator.writeObjectField(columnHeader, docRowData.getQueryCol2());
							}else if(queryColCounter == 2){
								jsonGenerator.writeObjectField(columnHeader, docRowData.getQueryCol3());
							}
							queryColCounter++;
						}else if(def.getUserIdIndex() == j){
							jsonGenerator.writeObjectField(columnHeader, docRowData.getUserId());
							userColCounter++;
						}else{
							
							jsonGenerator.writeObjectField(columnHeader, otherColumnData[j-queryColCounter-userColCounter]);
							
						}
					}
					
					jsonGenerator.writeEndObject();
					
				}
				
				jsonGenerator.writeEndArray();
				
			}
			
		});
		
		factory.addSpecificMapping(GridDataList.class,new JsonSerializer<GridDataList>() {

			public void serialize(GridDataList dataList,
					JsonGenerator jsonGenerator,
					SerializerProvider provider) throws IOException,
					JsonProcessingException {
				
				List<?> list = dataList.getRecords();
				Grid grid = dataList.getConfig();

				List<BeanPropertyDefinition> properties = null;
				SerializationConfig config = null;
				
				jsonGenerator.writeStartArray();
				for (int i = 0; i < list.size(); i++) {
					Object obj = list.get(i);
					
					jsonGenerator.writeStartObject();
					
					if(properties == null){
						config = provider.getConfig();
						properties = config.introspect(provider.constructType(obj.getClass())).findProperties();
					}

					for (int n = 0; n < properties.size(); n++) {
						
						BeanPropertyDefinition property = properties.get(n);
						Column col = XmlViewManager.getColumn(grid,property.getName());
						
						//if(col == null){continue;}
						
						try {
							Object value = property.getGetter().getAnnotated().invoke(obj);

							if (col != null && col.getRenderer() != null) {
								value = col.getRendererMap().get(value);
							}
							
							//_serializerProvider.serializeValue(config, jsonGenerator, value, _serializerFactory);
							//JsonObjectMapper.this.wr
							//StdSerializerProvider provider1 = (StdSerializerProvider)provider;
							//BeanSerializer ser = (BeanSerializer)provider1.findTypedValueSerializer(obj.getClass(), true);
							//ser.serialize(bean, jgen, provider1);
							
							jsonGenerator.writeObjectField(property.getName(), value);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
					jsonGenerator.writeEndObject();
				}
				jsonGenerator.writeEndArray();
				
			}
		});

		factory.addSpecificMapping(ArrayList.class,new JsonSerializer<ArrayList>() {
			public void serialize(ArrayList list,
					JsonGenerator jsonGenerator,
					SerializerProvider provider) throws IOException,
					JsonProcessingException {

				jsonGenerator.writeStartArray();
				for (int i = 0; i < list.size(); i++) {
					Object obj = list.get(i);
					jsonGenerator.writeObject(obj);
				}
				jsonGenerator.writeEndArray();
			}
		});

		this.setSerializerFactory(factory);
	}
	
}
